package com.yami.shop.mystery.api.controller;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.yami.shop.bean.app.dto.*;
import com.yami.shop.bean.app.param.SubmitOrderParam;
import com.yami.shop.bean.enums.EsOperationType;
import com.yami.shop.bean.enums.OrderType;
import com.yami.shop.bean.enums.ProdStatusEnums;
import com.yami.shop.bean.event.EsProductUpdateEvent;
import com.yami.shop.bean.model.Order;
import com.yami.shop.bean.model.Product;
import com.yami.shop.bean.model.ShopDetail;
import com.yami.shop.bean.model.ShopDivisionReceiver;
import com.yami.shop.bean.param.ChooseCouponParam;
import com.yami.shop.bean.param.PlatformChooseCouponParam;
import com.yami.shop.bean.vo.UserDeliveryInfoVO;
import com.yami.shop.common.exception.YamiShopBindException;
import com.yami.shop.common.response.ResponseEnum;
import com.yami.shop.common.response.ServerResponseEntity;
import com.yami.shop.config.ShopConfig;
import com.yami.shop.delivery.api.manager.DeliveryOrderManager;
import com.yami.shop.manager.*;
import com.yami.shop.manager.impl.ConfirmOrderManager;
import com.yami.shop.manager.impl.ShopCartAdapter;
import com.yami.shop.manager.impl.ShopCartItemAdapter;
import com.yami.shop.mystery.api.service.ActivityPresellManager;
import com.yami.shop.mystery.common.api.param.PresellOrderParam;
import com.yami.shop.mystery.common.dto.ActivityPresellDto;
import com.yami.shop.mystery.common.dto.ActivityProdDto;
import com.yami.shop.mystery.common.enums.ActivityRuleEnum;
import com.yami.shop.mystery.common.service.ActivityPresellService;
import com.yami.shop.mystery.common.service.ActivityProdService;
import com.yami.shop.security.api.util.SecurityUtils;
import com.yami.shop.service.*;
import groovy.lang.Tuple;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.Valid;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.RoundingMode;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * @author wxf
 * @date 2023/4/20 17:17
 */
@Slf4j
@RestController
@AllArgsConstructor
@RequestMapping("/p/presell")
@Tag(name = "预售活动订单接口")
public class ActivityPresellOrderController {

    @Autowired
    private OrderService orderService;
    @Autowired
    private SubmitOrderManager submitOrderManager;
    @Autowired
    private SkuService skuService;
    @Autowired
    private ProductService productService;
    @Autowired
    private ApplicationEventPublisher eventPublisher;
    @Autowired
    private ShopCartAdapter shopCartAdapter;
    @Autowired
    private ShopCartItemAdapter shopCartItemAdapter;
    @Autowired
    private ConfirmOrderManager confirmOrderManager;
    @Autowired
    private ThreadPoolExecutor orderThreadPoolExecutor;
    @Autowired
    private DeliveryOrderManager deliveryOrderManager;
    @Autowired
    private DiscountShopCartManager discountShopCartManager;
    @Autowired
    private ComboShopCartManager comboShopCartManager;
    @Autowired
    private CouponConfirmOrderManager couponConfirmOrderManager;
    @Autowired
    private UserLevelOrderManager userLevelOrderManager;
    @Autowired
    private ActivityPresellService activityPresellService;
    @Autowired
    private ActivityPresellManager activityPresellManager;
    @Autowired
    private ActivityProdService activityProdService;
    @Autowired
    private ShopConfig shopConfig;
    @Autowired
    private ShopDetailService shopDetailService;
    @Autowired
    private ShopCustomerService shopCustomerService;
    @Autowired
    private ShopDivisionReceiverService shopDivisionReceiverService;

    @PostMapping("/confirm")
    @Operation(summary =  "结算，生成普通订单信息", description = "传入下单所需要的参数进行下单")
    public ServerResponseEntity<ShopCartOrderMergerDto> confirm(@Valid @RequestBody PresellOrderParam orderParam) {

        String userId = SecurityUtils.getUser().getUserId();
        // 校验购买权限
        ActivityProdDto activityProdDto;
        try {
            activityProdDto = checkActivityAndGetPresellPrice(orderParam, userId);
        } catch (Exception e) {
            return ServerResponseEntity.showFailMsg(e.getMessage());
        }
        if (null == activityProdDto) {
            return ServerResponseEntity.showFailMsg("活动信息校验失败");
        }
        List<ShopCartItemDto> shopCartItemsDb = shopCartItemAdapter.getShopCartItem(orderParam.getOrderItem(), activityProdDto.getPreemptionPrice(), userId, orderParam.getAddrId());

        // 将要返回给前端的完整的订单信息
        ShopCartOrderMergerDto shopCartOrderMerger = new ShopCartOrderMergerDto();
        shopCartOrderMerger.setDvyType(orderParam.getDvyType());
        shopCartOrderMerger.setOrderType(OrderType.PRESELL);
        shopCartOrderMerger.setActivityId(orderParam.getActivityId());

        // 筛选过滤掉不同配送的商品
        List<ShopCartItemDto> shopCartItems = confirmOrderManager.filterShopItemsByType(shopCartOrderMerger, shopCartItemsDb);
        // 该商品不满足任何的配送方式
        if (CollectionUtil.isEmpty(shopCartItems)) {
            return ServerResponseEntity.fail(ResponseEnum.ORDER_DELIVERY_NOT_SUPPORTED, shopCartOrderMerger);
        }
        ShopCartItemDto firstShopCartItem = shopCartItems.get(0);
        // 是否为预售订单
        orderParam.setPreSellStatus(firstShopCartItem.getPreSellStatus());
        shopCartOrderMerger.setPreSellStatus(firstShopCartItem.getPreSellStatus());
        // 商品类别 0.实物商品 1. 虚拟商品
        int mold = 0;
        if (shopCartItems.stream().filter(shopCartItemDto -> shopCartItemDto.getMold() == 1).count() == shopCartItems.size()) {
            // 订单项中的所有商品都为虚拟商品时，才是虚拟订单
            mold = 1;
        }
        shopCartOrderMerger.setMold(mold);

        // 购物车
        List<ShopCartDto> shopCarts = shopCartAdapter.getShopCarts(shopCartItems);

        // 计算满减，并重新组合购物车
        if (discountShopCartManager != null) {
            shopCarts = discountShopCartManager.calculateDiscountAndMakeUpShopCart(shopCarts);
        }

        // 计算套餐，并重新组合购物车
        if (comboShopCartManager != null) {
            shopCarts = comboShopCartManager.calculateDiscountAndMakeUpShopCart(shopCarts);
        }

        UserDeliveryInfoVO userDeliveryInfo = new UserDeliveryInfoVO();
        try {
            // 异步计算运费，运费暂时和优惠券没啥关联，可以与优惠券异步计算，获取用户地址，自提信息
            CompletableFuture<UserDeliveryInfoVO> deliveryFuture = null;
            if (Objects.equals(mold, 0)) {
                deliveryFuture = CompletableFuture.supplyAsync(
                        () -> deliveryOrderManager.calculateAndGetDeliverInfo(userId, orderParam.getAddrId(), orderParam.getDvyType(), shopCartItems),
                        orderThreadPoolExecutor);
            }

            // 计算优惠券，并返回优惠券信息
            if (couponConfirmOrderManager != null) {
                shopCarts = couponConfirmOrderManager.chooseShopCoupon(new ChooseCouponParam(orderParam.getUserChangeCoupon(), orderParam.getCouponUserIds(), shopCarts));
            }

            // 运费用异步计算，最后要等运费出结果
            if (Objects.nonNull(deliveryFuture)) {
                userDeliveryInfo = deliveryFuture.get();
            }
        } catch (Exception e) {
        }

        // 当算完一遍店铺的各种满减活动时，重算一遍订单金额
        confirmOrderManager.recalculateAmountWhenFinishingCalculateShop(shopCartOrderMerger, shopCarts, userDeliveryInfo);

        double orderShopReduce = shopCartOrderMerger.getOrderReduce();

        // ===============================================开始平台优惠的计算==================================================

        // 计算平台优惠券，并返回平台优惠券信息
        if (couponConfirmOrderManager != null) {
            shopCartOrderMerger = couponConfirmOrderManager.choosePlatformCoupon(new PlatformChooseCouponParam(orderParam.getUserChangeCoupon(), orderParam.getCouponUserIds(), shopCartOrderMerger));
        }

        // 等级折扣
        if (userLevelOrderManager != null) {
            userLevelOrderManager.calculateLevelDiscount(shopCartOrderMerger);
        }

        // ===============================================结束平台优惠的计算==================================================
        // 结束平台优惠的计算之后，还要重算一遍金额
        confirmOrderManager.recalculateAmountWhenFinishingCalculatePlatform(shopCartOrderMerger);

        /*// 计算订单积分抵扣金额
        if (orderUseScoreManager != null) {
            orderUseScoreManager.orderUseScore(shopCartOrderMerger, orderParam, shopCartItems);
        }*/
        shopCartOrderMerger.setOrderShopReduce(orderShopReduce);
        // 计算平台佣金
        confirmOrderManager.calculatePlatformCommission(shopCartOrderMerger);

        // 缓存计算
        confirmOrderManager.cacheCalculatedInfo(userId, shopCartOrderMerger);
        return ServerResponseEntity.success(shopCartOrderMerger);
    }

    @PostMapping("/submit")
    @Operation(summary =  "提交订单，返回支付流水号", description = "根据传入的参数判断是否为购物车提交订单，同时对购物车进行删除，用户开始进行支付，根据店铺进行拆单")
    public ServerResponseEntity<Map> submitOrders(@Valid @RequestBody SubmitOrderParam submitOrderParam) {
        String userId = SecurityUtils.getUser().getUserId();
        ServerResponseEntity<ShopCartOrderMergerDto> orderCheckResult = submitOrderManager.checkSubmitInfo(submitOrderParam, userId);
        if (!orderCheckResult.isSuccess()) {
            if(StrUtil.equals(ResponseEnum.REPEAT_ORDER.value(),orderCheckResult.getCode())){
                OrderNumbersDto orderNumbersDto = new OrderNumbersDto(null);
                orderNumbersDto.setDuplicateError(1);
                throw new YamiShopBindException("订单已过期，请重新下单");
            }
        }
        ShopCartOrderMergerDto mergerOrder = orderCheckResult.getData();
        //查询店铺新生信息
        ShopDetail shopDetailByShopId = shopDetailService.getShopDetailByShopId(mergerOrder.getShopCartOrders().get(0).getShopId());
        if(ObjectUtils.isEmpty(shopDetailByShopId.getShopXsUserId())){
            throw new YamiShopBindException("该店铺未绑定新生账号");
        }
        StringBuilder orderNumbers = new StringBuilder();
        List<ShopCartOrderDto> shopCartOrders = mergerOrder.getShopCartOrders();
        for (ShopCartOrderDto shopCartOrder : shopCartOrders) {
            List<ShopCartItemDiscountDto> shopCartItemDiscounts = shopCartOrder.getShopCartItemDiscounts();
            for (ShopCartItemDiscountDto shopCartItemDiscount : shopCartItemDiscounts) {
                orderNumbers.append(shopCartOrder.getOrderNumber()).append(StrUtil.COMMA);
                List<ShopCartItemDto> shopCartItems = shopCartItemDiscount.getShopCartItems();
                for (ShopCartItemDto shopCartItem : shopCartItems) {
                    Long prodId = shopCartItem.getProdId();
                    Product productById = productService.getProductById(prodId);
                    if (productById.getStatus() != ProdStatusEnums.NORMAL.getValue() && productById.getStatus() != ProdStatusEnums.PRESELL.getValue()) {
                        throw new YamiShopBindException("商品:["+productById.getProdName()+"]已下架");
                    }
                    // 这里一进来就减库存，但是为了防止少卖，120秒会自己更新库存~因为缓存只有60秒
                    activityProdService.decrActivitySkuStocks(mergerOrder.getActivityId(),shopCartItem.getProdCount(),prodId );
                    // 更新活动商品sku库存，乐观锁
                    if (activityProdService.updateStocks(mergerOrder.getActivityId(), prodId,shopCartItem.getProdCount()) != 1) {
                        // 本商品已被秒杀完毕，下次记得早点来哟
                        throw new YamiShopBindException("yami.seckill.finish");
                    }
                    // 更新活动剩余库存
                    if (activityPresellService.updateStocksById(mergerOrder.getActivityId(), shopCartItem.getProdCount()) < 1) {
                        // 本商品已被秒杀完毕，下次记得早点来哟
                        throw new YamiShopBindException("yami.seckill.finish");
                    }
                }
            }
        }
        orderNumbers.deleteCharAt(orderNumbers.length() - 1);
        try {
            // EXECUTOR.execute(() -> {
                orderService.submit(mergerOrder);
            // });
        } catch (RejectedExecutionException e) {
            // 服务器繁忙，请稍后再试
            throw new YamiShopBindException("yami.network.busy");
        }
        List<LedgerOrderDto> ledgerOrderDtos = new ArrayList<>();
        // 所有商品分账总计
        BigDecimal allDivide = new BigDecimal(BigInteger.ZERO);
        // 移除缓存
        for (ShopCartOrderDto shopCartOrder : shopCartOrders) {
            for (ShopCartItemDiscountDto shopCartItemDiscount : shopCartOrder.getShopCartItemDiscounts()) {
                for (ShopCartItemDto shopCartItem : shopCartItemDiscount.getShopCartItems()) {
                    skuService.removeSkuCacheBySkuId(shopCartItem.getSkuId(), shopCartItem.getProdId());
                    productService.removeProdCacheByProdId(shopCartItem.getProdId());
                    activityProdService.removeActivitySkuCache(mergerOrder.getActivityId(), shopCartItem.getProdId());
                    // 计算每个商品的分账信息
                    if(ObjectUtil.isNotNull(shopCartItem.getReceiverGroupId())){
                        List<ShopDivisionReceiver> receivers = shopDivisionReceiverService.list(
                                new LambdaQueryWrapper<ShopDivisionReceiver>()
                                        .eq(ShopDivisionReceiver::getReceiverGroupId, shopCartItem.getReceiverGroupId())
                                        .eq(ShopDivisionReceiver::getShopId, shopDetailByShopId.getShopId())
                                        .eq(ShopDivisionReceiver::getState, 1));
                        for (ShopDivisionReceiver receiver : receivers) {
                            LedgerOrderDto divideAcct = new LedgerOrderDto();
                            divideAcct.setLedgerUserId(receiver.getAccNo());
                            BigDecimal divide = new BigDecimal(String.valueOf(mergerOrder.getTotal())).multiply(receiver.getDivisionProfit()).setScale(2, RoundingMode.HALF_DOWN);
                            divideAcct.setAmount(divide.toString());
                            ledgerOrderDtos.add(divideAcct);
                            allDivide = allDivide.add(divide);
                        }
                    }
                }
            }
        }
        orderService.removeConfirmOrderCache(userId + submitOrderParam.getUuid());
        // 更新es中的商品库存--更新失败打印日志，优先保证订单流程没问题
        try {
            eventPublisher.publishEvent(new EsProductUpdateEvent(mergerOrder.getProdList(), EsOperationType.UPDATE_ORDER_STOCK_NUM_BATCH));
        } catch (Exception e) {
            log.error("提交订单-更新es商品库存失败，错误为：{}", e);
        }



        // 店铺客户创建
        Order order = new Order();
        order.setUserId(userId);
        order.setShopId(shopCartOrders.get(0).getShopId());
        shopCustomerService.saveCustomerByOrders(Collections.singletonList(order));
        // 平台佣金分账信息
        LedgerOrderDto merchantToPlatform = new LedgerOrderDto();
        merchantToPlatform.setLedgerUserId(shopConfig.getHnaPay().getMerId());
        merchantToPlatform.setAmount(mergerOrder.getShopCartOrders().get(0).getPlatformCommission().toString());
        ledgerOrderDtos.add(merchantToPlatform);
        // 计算店铺剩余分账金额
        LedgerOrderDto merchantToShop  = new LedgerOrderDto();
        merchantToShop.setLedgerUserId(shopDetailByShopId.getShopXsUserId());
        //店铺剩余分账金额
        BigDecimal shopAmount = new BigDecimal(String.valueOf(mergerOrder.getTotal())).subtract(new BigDecimal(String.valueOf(mergerOrder.getShopCartOrders().get(0).getPlatformCommission()))).subtract(allDivide);
        merchantToShop.setAmount(String.valueOf(shopAmount));
        ledgerOrderDtos.add(merchantToShop);
        Map<Object,Object> orderMap = new HashMap<>();
        orderMap.put("ledgerOrderDtos", JSONUtil.toJsonStr(ledgerOrderDtos));
        orderMap.put("orderNumbers",orderNumbers);

        return ServerResponseEntity.success(orderMap);
    }

    /**
     * 检查活动状态
     */
    private ActivityProdDto checkActivityAndGetPresellPrice(PresellOrderParam orderParam, String userId) {
        Long prodId = orderParam.getOrderItem().getProdId();
        ActivityPresellDto activityDto = activityPresellService.detail(orderParam.getActivityId());
        if (Objects.isNull(activityDto) || !Objects.equals(activityDto.getStatus(), 0)
                || activityDto.getActivityEndTime().getTime() < System.currentTimeMillis()
                || activityDto.getActivityStartTime().getTime() > System.currentTimeMillis()) {
            // 预售活动不在进行中，请稍后重试
            throw new YamiShopBindException("预售活动不在进行中，请稍后重试");
        }

        if(ObjectUtil.isNotNull(activityDto.getTotalStocks())){
            if(activityDto.getTotalStocks() <= 0 || activityDto.getTotalStocks() - orderParam.getOrderItem().getProdCount() < 0){
                throw new YamiShopBindException("活动商品库存不足！");
            }
        }


        ActivityProdDto prodDto = null;
        List<ActivityProdDto> prods = activityDto.getProds();
        for (ActivityProdDto dto : prods) {
            if (Objects.equals(dto.getProdId(), prodId)) {
                prodDto = dto;
                break;
            }
        }
        if (Objects.isNull(prodDto)) {
            // 活动商品不在正常状态
            throw new YamiShopBindException("yami.group.prod.status.error");
        }

        activityDto.setSpuId(prodId);
        Tuple tuple = activityPresellManager.checkUser(activityDto, userId);
        if (!(boolean) tuple.get(0)) {
            // 活动商品不在正常状态
            throw new YamiShopBindException("用户无法购买");
        }

        Long maxNum = (Long) tuple.get(1);
        if (!(boolean) tuple.get(4)) {
            // 预售活动不在进行中，请稍后重试
            throw new YamiShopBindException("用户无法购买");
        }
        String ruleType = (String)tuple.get(5);
        if (ActivityRuleEnum.DISCOUNTS.getValue().equals(ruleType)) {
            BigDecimal pric = new BigDecimal(activityDto.getPreemptionPrice() + "").divide(new BigDecimal("100")).setScale(2, BigDecimal.ROUND_HALF_UP);
            prodDto.setPreemptionPrice(pric.doubleValue());
        }
        /**
         * 限购数 不等于0 是限购
         */
        if(maxNum != 0) {
            // 大于限购数量
            if (orderParam.getOrderItem().getProdCount() > maxNum.intValue()) {
                log.error("orderConfirm111-{} 您购买数量超出限购数量{}",userId,maxNum);
                throw new YamiShopBindException("您购买数量超出限购数量");
            }
        }

        if(ObjectUtil.isNotNull(prodDto.getProdTotalStocks())){
            if(prodDto.getProdTotalStocks() <= 0 || prodDto.getProdTotalStocks().intValue() - orderParam.getOrderItem().getProdCount() < 0){
                throw new YamiShopBindException("活动商品库存不足！");
            }
        }

        if(ObjectUtil.isNotNull(prodDto.getPurchaseNum())){
            if (orderParam.getOrderItem().getProdCount() > prodDto.getPurchaseNum()) {
                log.info("orderConfirm222-{} 您购买数量超出限购数量{}",userId,prodDto.getPurchaseNum());
                throw new YamiShopBindException("您购买数量超出限购数量");
            }
            // 小于限购数量
            Integer orderPurchaseCount = orderService.getOrderPurchaseCount(userId, orderParam.getOrderItem().getProdId(),orderParam.getActivityId());
            if (orderPurchaseCount <= prodDto.getPurchaseNum()) {
                // 剩余限购数量
                Integer counts = prodDto.getPurchaseNum() - orderPurchaseCount;
                if (orderParam.getOrderItem().getProdCount() > counts) {
                    log.info("orderConfirm333-{} 您购买数量超出限购数量{}!",userId,counts);
                    throw new YamiShopBindException("您购买数量超出限购数量");
                }
            }
        }

        return prodDto;
    }

}
